package jxtcpclient

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"math/rand"

	"github.com/google/uuid"
	"github.com/vmihailenco/msgpack/v5"
)

const (
	MagicNumber uint32 = 0xCAFEBABE // 协议魔数 [[3]]
	Version     uint16 = 1          // 协议版本 [[10]]
)

func GetRandInt(min, max int) int {
	if min == max {
		return min // 如果 min 和 max 相等，直接返回该值
	}
	if min > max {
		min, max = max, min // 确保 min ≤ max，自动调整顺序
	}
	return rand.Intn(max-min+1) + min
}
func GetRandFloat(min, max float64) float64 {
	if min == max {
		return min // 如果 min 和 max 相等，直接返回该值
	}
	if min > max {
		min, max = max, min // 确保 min ≤ max，自动调整顺序
	}
	return min + rand.Float64()*(max-min)
}

type Message struct {
	Id        string // 消息ID，每次发送和接收对应
	Title     string // 消息标题，用于调试
	MoreInfo  string // 消息附加信息
	Type      uint32 // 消息类型
	MachineId uint32 // 机器码，对应每个客户端
	Data      []byte // 消息内容，用于解析为不同的消息
}

func (m *Message) GetProgress() (*Progress, error) {
	outData := new(Progress)
	err := msgpack.Unmarshal(m.Data, outData)
	return outData, err
}

// ToByte 将 Message 结构体序列化为字节切片
func (m *Message) ToByte() (int64, []byte, error) {
	body, err := msgpack.Marshal(m)
	return int64(len(body)), body, err
}

// FromByte 将字节切片反序列化为 Message 结构体
func FromByte(data []byte) (*Message, error) {
	outData := new(Message)
	err := msgpack.Unmarshal(data, outData)
	return outData, err
}

// 辅助函数：写入字符串（先写入长度，再写入内容）
func writeString(buf *bytes.Buffer, s string) error {
	length := uint32(len(s))
	if err := binary.Write(buf, binary.LittleEndian, length); err != nil {
		return err
	}
	_, err := buf.WriteString(s)
	return err
}

// 辅助函数：读取字符串
func readString(buf *bytes.Reader) (string, error) {
	var length uint32
	if err := binary.Read(buf, binary.LittleEndian, &length); err != nil {
		return "", err
	}
	data := make([]byte, length)
	if _, err := buf.Read(data); err != nil {
		return "", err
	}
	return string(data), nil
}

// 辅助函数：写入字节切片（先写入长度，再写入内容）
func writeBytes(buf *bytes.Buffer, b []byte) error {
	length := uint32(len(b))
	if err := binary.Write(buf, binary.LittleEndian, length); err != nil {
		return err
	}
	_, err := buf.Write(b)
	return err
}

// 辅助函数：读取字节切片
func readBytes(buf *bytes.Reader) ([]byte, error) {
	var length uint32
	if err := binary.Read(buf, binary.LittleEndian, &length); err != nil {
		return nil, err
	}
	data := make([]byte, length)
	if _, err := buf.Read(data); err != nil {
		return nil, err
	}
	return data, nil
}

type Progress struct {
	Max   float64
	Value float64
	Add   float64
}

func NewMessage(title, moreinfo string, _type, machineid uint32, data []byte) *Message {
	return &Message{
		Id:        uuid.NewString(),
		Title:     title,
		MoreInfo:  moreinfo,
		Type:      _type,
		MachineId: machineid,
		Data:      data,
	}
}

func ReadMessage(r *bufio.Reader) (*Message, error) {
	if r == nil {
		return nil, fmt.Errorf("当前链接尚未准备好")
	}

	var count int64
	err := binary.Read(r, binary.BigEndian, &count)
	if err != nil || count < 1 {
		return nil, fmt.Errorf("数据长度错误")
	}

	body := make([]byte, count)
	n, err := io.ReadFull(r, body)
	if err != nil {
		return nil, fmt.Errorf("读取消息体失败: %w", err)
	}
	if int64(n) != count {
		return nil, fmt.Errorf("读取字节数不匹配: expected %d, got %d", count, n)
	}
	msg, err := FromByte(body)
	return msg, err
}

// WriteMessage 写入消息（带协议头）
func (m *Message) WriteMessage(w *bufio.Writer) error {
	if w == nil {
		return fmt.Errorf("当前链接尚未准备好")
	}
	count, body, err := m.ToByte()
	if err != nil {
		return err
	}
	err = binary.Write(w, binary.BigEndian, count)
	if err != nil {
		return err
	}
	_, err = w.Write(body)
	if err != nil {
		return err
	}
	return w.Flush()
}
func ValidateHeader(r io.Reader) error {
	// 读取协议头（MagicNumber + Version）
	header := make([]byte, 6)
	if _, err := io.ReadFull(r, header); err != nil {
		return fmt.Errorf("failed to read protocol header: %w", err)
	}
	// 解析 MagicNumber
	magic := binary.BigEndian.Uint32(header[:4])
	if magic != MagicNumber {
		return fmt.Errorf("协议错误，无法读取")
	}
	// 解析 Version
	version := binary.BigEndian.Uint16(header[4:6])
	if version != Version {
		return fmt.Errorf("版本号错误，无法读取")
	}
	// 验证通过
	return nil
}

// WriteHeader 将 MagicNumber 和 Version 写入输出流
func WriteHeader(w io.Writer) error {
	// 创建缓冲区
	buf := make([]byte, 6)
	// 写入 MagicNumber
	binary.BigEndian.PutUint32(buf[:4], MagicNumber)

	// 写入 Version
	binary.BigEndian.PutUint16(buf[4:6], Version)

	// 写入到输出流
	if _, err := w.Write(buf); err != nil {
		return fmt.Errorf("写入版本号错误: %w", err)
	}

	return nil
}
